const fs = require('fs');
const path = require('path');
const acorn = require('acorn');
const walk = require('acorn-walk');
const astring = require('astring');

// 转换单个文件
function convertFileContent(content) {
  try {
    const ast = acorn.parse(content, {
      ecmaVersion: 'latest',
      sourceType: 'module',
      locations: true,
      onComment: [] // 启用注释收集
    });

    const constructors = new Map();
    const skipNodes = new Set();
    const exportDeclarations = new Map();
    const comments = ast.comments || []; // 保存所有注释

    // 第一轮遍历：收集构造函数和导出声明
    walk.simple(ast, {
      FunctionDeclaration(node) {
        if (node.id && /^[A-Z]/.test(node.id.name)) {
          constructors.set(node.id.name, {
            node: node,
            methods: [],
            staticMethods: []
          });
        }
      },
      
      ExportDefaultDeclaration(node) {
        if (node.declaration.type === 'Identifier') {
          exportDeclarations.set('default', node.declaration.name);
        }
      },
      
      ExportNamedDeclaration(node) {
        if (node.declaration && node.declaration.type === 'FunctionDeclaration' && 
            node.declaration.id && /^[A-Z]/.test(node.declaration.id.name)) {
          constructors.set(node.declaration.id.name, {
            node: node.declaration,
            methods: [],
            staticMethods: []
          });
          skipNodes.add(node);
        }
      }
    });

    // 第二轮遍历：收集原型方法和静态方法
    walk.simple(ast, {
      ExpressionStatement(node) {
        if (node.expression.type === 'AssignmentExpression') {
          const assignment = node.expression;
          const left = assignment.left;
          
          // 原型方法: Constructor.prototype.method
          if (left.type === 'MemberExpression' &&
              left.object.type === 'MemberExpression' &&
              left.object.property && 
              left.object.property.type === 'Identifier' &&
              left.object.property.name === 'prototype' &&
              left.object.object && 
              left.object.object.type === 'Identifier') {
            
            const ctorName = left.object.object.name;
            if (constructors.has(ctorName)) {
              const methodName = left.property.type === 'Identifier' ? left.property.name : null;
              if (methodName && assignment.right.type === 'FunctionExpression') {
                constructors.get(ctorName).methods.push({
                  name: methodName,
                  node: assignment.right
                });
                skipNodes.add(node);
              }
            }
          }
          
          // 静态方法: Constructor.method
          else if (left.type === 'MemberExpression' &&
                   left.object && 
                   left.object.type === 'Identifier' &&
                   constructors.has(left.object.name) &&
                   left.property.type === 'Identifier' &&
                   assignment.right.type === 'FunctionExpression') {
            
            const ctorName = left.object.name;
            const methodName = left.property.name;
            constructors.get(ctorName).staticMethods.push({
              name: methodName,
              node: assignment.right
            });
            skipNodes.add(node);
          }
        }
      }
    });

    // 构建新的AST body
    const newBody = [];
    let hasDefaultExport = false;
    
    for (const node of ast.body) {
      if (skipNodes.has(node)) continue;
      
      // 处理函数声明
      if (node.type === 'FunctionDeclaration' && constructors.has(node.id.name)) {
        const ctorInfo = constructors.get(node.id.name);
        
        const classNode = createClassNode(ctorInfo);
        
        // 保留原函数前的注释
        classNode.leadingComments = node.leadingComments;
        newBody.push(classNode);
        
        // 检查是否需要导出默认
        if (exportDeclarations.get('default') === node.id.name) {
          hasDefaultExport = true;
        }
      }
      // 处理命名导出函数声明
      else if (node.type === 'ExportNamedDeclaration' && 
               node.declaration && 
               node.declaration.type === 'FunctionDeclaration' && 
               constructors.has(node.declaration.id.name)) {
        const ctorInfo = constructors.get(node.declaration.id.name);
        newBody.push({
          type: 'ExportNamedDeclaration',
          declaration: createClassNode(ctorInfo)
        });
      }
      else {
        newBody.push(node);
      }
    }
    
    // // 添加默认导出
    // if (hasDefaultExport) {
    //   newBody.push({
    //     type: 'ExportDefaultDeclaration',
    //     declaration: { type: 'Identifier', name: exportDeclarations.get('default') }
    //   });
    // }

    // 创建新AST并添加注释
    const newAst = {
      type: 'Program',
      body: newBody,
      sourceType: 'module',
      comments: comments
    };

    // 生成新代码并保留注释
    return astring.generate(newAst, {
      indent: '  ',
      lineEnd: '\n',
      comments: true // 保留注释
    });
  } catch (error) {
    console.error('解析错误，返回原始内容:', error.message);
    return content;
  }
}

// 创建类节点
function createClassNode(ctorInfo) {
  return {
    type: 'ClassDeclaration',
    id: { type: 'Identifier', name: ctorInfo.node.id.name },
    superClass: null,
    body: {
      type: 'ClassBody',
      body: [
        // 构造函数
        {
          type: 'MethodDefinition',
          kind: 'constructor',
          static: false,
          computed: false,
          key: { type: 'Identifier', name: 'constructor' },
          value: {
            type: 'FunctionExpression',
            id: null,
            params: ctorInfo.node.params,
            body: ctorInfo.node.body,
            generator: false,
            async: false,
            expression: false
          }
        },
        // 原型方法
        ...ctorInfo.methods.map(method => ({
          type: 'MethodDefinition',
          kind: 'method',
          static: false,
          computed: false,
          key: { type: 'Identifier', name: method.name },
          value: {
            type: 'FunctionExpression',
            id: null,
            params: method.node.params,
            body: method.node.body,
            generator: false,
            async: false,
            expression: false
          }
        })),
        // 静态方法
        ...ctorInfo.staticMethods.map(method => ({
          type: 'MethodDefinition',
          kind: 'method',
          static: true,
          computed: false,
          key: { type: 'Identifier', name: method.name },
          value: {
            type: 'FunctionExpression',
            id: null,
            params: method.node.params,
            body: method.node.body,
            generator: false,
            async: false,
            expression: false
          }
        }))
      ]
    }
  };
}

// 处理目录
async function convertDirectory(sourceDir, targetDir) {
  await fs.promises.mkdir(targetDir, { recursive: true });

  const entries = await fs.promises.readdir(sourceDir, { withFileTypes: true });

  for (const entry of entries) {
    const srcPath = path.join(sourceDir, entry.name);
    const destPath = path.join(targetDir, entry.name);

    if (entry.isDirectory()) {
      await convertDirectory(srcPath, destPath);
    } else if (entry.isFile() && path.extname(entry.name) === '.js') {
      const content = await fs.promises.readFile(srcPath, 'utf8');
      const converted = convertFileContent(content);
      await fs.promises.writeFile(destPath, converted);
      console.log(`转换完成: ${srcPath} -> ${destPath}`);
    } else {
      await fs.promises.copyFile(srcPath, destPath);
    }
  }
}

// 主函数
async function main() {
  let [sourceDir, targetDir] = process.argv.slice(2);
  
  if (!sourceDir || !targetDir) {
    console.log('用法: node convert.js <源目录> <目标目录>');
    console.log('示例: node convert.js ./src ./dist');
    // process.exit(1);
    sourceDir = './src';
    targetDir = './dist';
  }

  try {
    await convertDirectory(path.resolve(sourceDir), path.resolve(targetDir));
    console.log('所有文件转换完成！');
  } catch (error) {
    console.error('转换过程中出错:', error);
    process.exit(1);
  }
}

main();